home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / copypix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  14.4 KB  |  503 lines

  1. /* $Id: copypix.c,v 1.3 1996/09/15 14:18:10 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.0
  6.  * Copyright (C) 1995-1996  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: copypix.c,v $
  26.  * Revision 1.3  1996/09/15 14:18:10  brianp
  27.  * now use GLframebuffer and GLvisual
  28.  *
  29.  * Revision 1.2  1996/09/15 01:48:58  brianp
  30.  * removed #define NULL 0
  31.  *
  32.  * Revision 1.1  1996/09/13 01:38:16  brianp
  33.  * Initial revision
  34.  *
  35.  */
  36.  
  37.  
  38. #include <string.h>
  39. #include "context.h"
  40. #include "copypix.h"
  41. #include "depth.h"
  42. #include "feedback.h"
  43. #include "dlist.h"
  44. #include "macros.h"
  45. #include "pixel.h"
  46. #include "span.h"
  47. #include "stencil.h"
  48. #include "types.h"
  49.  
  50.  
  51.  
  52.  
  53. static void copy_rgb_pixels( GLcontext* ctx,
  54.                              GLint srcx, GLint srcy, GLint width, GLint height,
  55.                              GLint destx, GLint desty )
  56. {
  57.    DEFARRAY( GLdepth, zspan, MAX_WIDTH );
  58.    DEFARRAY( GLubyte, red, MAX_WIDTH );
  59.    DEFARRAY( GLubyte, green, MAX_WIDTH );
  60.    DEFARRAY( GLubyte, blue, MAX_WIDTH );
  61.    DEFARRAY( GLubyte, alpha, MAX_WIDTH );
  62.    GLboolean scale_or_bias, quick_draw, zoom;
  63.    GLint sy, dy, stepy;
  64.    GLint i, j;
  65.    GLboolean setbuffer;
  66.  
  67.    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  68.       zoom = GL_FALSE;
  69.    }
  70.    else {
  71.       zoom = GL_TRUE;
  72.    }
  73.  
  74.    /* Determine if copy should be done bottom-to-top or top-to-bottom */
  75.    if (srcy<desty) {
  76.       /* top-down  max-to-min */
  77.       sy = srcy + height - 1;
  78.       dy = desty + height - 1;
  79.       stepy = -1;
  80.    }
  81.    else {
  82.       /* bottom-up  min-to-max */
  83.       sy = srcy;
  84.       dy = desty;
  85.       stepy = 1;
  86.    }
  87.  
  88.    scale_or_bias = ctx->Pixel.RedScale!=1.0 || ctx->Pixel.RedBias!=0.0
  89.                 || ctx->Pixel.GreenScale!=1.0 || ctx->Pixel.GreenBias!=0.0
  90.         || ctx->Pixel.BlueScale!=1.0 || ctx->Pixel.BlueBias!=0.0
  91.         || ctx->Pixel.AlphaScale!=1.0 || ctx->Pixel.AlphaBias!=0.0;
  92.  
  93.    if (ctx->Depth.Test) {
  94.       /* fill in array of z values */
  95.       GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  96.       for (i=0;i<width;i++) {
  97.          zspan[i] = z;
  98.       }
  99.    }
  100.  
  101.    if (ctx->RasterMask==0 && !zoom
  102.        && destx>=0 && destx+width<=ctx->Buffer->Width) {
  103.       quick_draw = GL_TRUE;
  104.    }
  105.    else {
  106.       quick_draw = GL_FALSE;
  107.    }
  108.  
  109.    /* If read and draw buffer are different we must do buffer switching */
  110.    setbuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
  111.  
  112.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  113.       /* read */
  114.  
  115.       if (setbuffer) {
  116.          (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  117.       }
  118.       gl_read_color_span( ctx, width, srcx, sy, red, green, blue, alpha );
  119.  
  120.       if (scale_or_bias) {
  121.          GLfloat rbias = ctx->Pixel.RedBias   * ctx->Visual->RedScale;
  122.          GLfloat gbias = ctx->Pixel.GreenBias * ctx->Visual->GreenScale;
  123.          GLfloat bbias = ctx->Pixel.BlueBias  * ctx->Visual->BlueScale;
  124.          GLfloat abias = ctx->Pixel.AlphaBias * ctx->Visual->AlphaScale;
  125.          GLint rmax = (GLint) ctx->Visual->RedScale;
  126.          GLint gmax = (GLint) ctx->Visual->GreenScale;
  127.          GLint bmax = (GLint) ctx->Visual->BlueScale;
  128.          GLint amax = (GLint) ctx->Visual->AlphaScale;
  129.          for (i=0;i<width;i++) {
  130.             GLint r = red[i]   * ctx->Pixel.RedScale   + rbias;
  131.             GLint g = green[i] * ctx->Pixel.GreenScale + gbias;
  132.             GLint b = blue[i]  * ctx->Pixel.BlueScale  + bbias;
  133.             GLint a = alpha[i] * ctx->Pixel.AlphaScale + abias;
  134.             red[i]   = CLAMP( r, 0, rmax );
  135.             green[i] = CLAMP( g, 0, gmax );
  136.             blue[i]  = CLAMP( b, 0, bmax );
  137.             alpha[i] = CLAMP( a, 0, amax );
  138.          }
  139.       }
  140.  
  141.       if (ctx->Pixel.MapColorFlag) {
  142.          GLfloat r = (ctx->Pixel.MapRtoRsize-1) * ctx->Visual->InvRedScale;
  143.          GLfloat g = (ctx->Pixel.MapGtoGsize-1) * ctx->Visual->InvGreenScale;
  144.          GLfloat b = (ctx->Pixel.MapBtoBsize-1) * ctx->Visual->InvBlueScale;
  145.          GLfloat a = (ctx->Pixel.MapAtoAsize-1) * ctx->Visual->InvAlphaScale;
  146.          for (i=0;i<width;i++) {
  147.             GLint ir = red[i] * r;
  148.             GLint ig = green[i] * g;
  149.             GLint ib = blue[i] * b;
  150.             GLint ia = alpha[i] * a;
  151.             red[i]   = (GLint) (ctx->Pixel.MapRtoR[ir]*ctx->Visual->RedScale);
  152.             green[i] = (GLint) (ctx->Pixel.MapGtoG[ig]*ctx->Visual->GreenScale);
  153.             blue[i]  = (GLint) (ctx->Pixel.MapBtoB[ib]*ctx->Visual->BlueScale);
  154.             alpha[i] = (GLint) (ctx->Pixel.MapAtoA[ia]*ctx->Visual->AlphaScale);
  155.          }
  156.       }
  157.  
  158.       /* write */
  159.       if (setbuffer) {
  160.          (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  161.       }
  162.       if (quick_draw && dy>=0 && dy<ctx->Buffer->Height) {
  163.          (*ctx->Driver.WriteColorSpan)( ctx, width, destx, dy,
  164.                                  red, green, blue, alpha, NULL);
  165.       }
  166.       else if (zoom) {
  167.          gl_write_zoomed_color_span( ctx, width, destx, dy, zspan,
  168.                                      red, green, blue, alpha, desty );
  169.       }
  170.       else {
  171.          gl_write_color_span( ctx, width, destx, dy, zspan,
  172.                               red, green, blue, alpha, GL_BITMAP );
  173.       }
  174.    }
  175.    UNDEFARRAY( zspan );
  176.    UNDEFARRAY( red );
  177.    UNDEFARRAY( green );
  178.    UNDEFARRAY( blue );
  179.    UNDEFARRAY( alpha );
  180. }
  181.  
  182.  
  183.  
  184. static void copy_ci_pixels( GLcontext* ctx,
  185.                             GLint srcx, GLint srcy, GLint width, GLint height,
  186.                             GLint destx, GLint desty )
  187. {
  188.    GLdepth zspan[MAX_WIDTH];
  189.    GLuint indx[MAX_WIDTH];
  190.    GLint sy, dy, stepy;
  191.    GLint i, j;
  192.    GLboolean setbuffer, zoom;
  193.  
  194.    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  195.       zoom = GL_FALSE;
  196.    }
  197.    else {
  198.       zoom = GL_TRUE;
  199.    }
  200.  
  201.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  202.    if (srcy<desty) {
  203.       /* top-down  max-to-min */
  204.       sy = srcy + height - 1;
  205.       dy = desty + height - 1;
  206.       stepy = -1;
  207.    }
  208.    else {
  209.       /* bottom-up  min-to-max */
  210.       sy = srcy;
  211.       dy = desty;
  212.       stepy = 1;
  213.    }
  214.  
  215.    if (ctx->Depth.Test) {
  216.       /* fill in array of z values */
  217.       GLint z = (GLint) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
  218.       for (i=0;i<width;i++) {
  219.          zspan[i] = z;
  220.       }
  221.    }
  222.  
  223.    /* If read and draw buffer are different we must do buffer switching */
  224.    setbuffer = ctx->Pixel.ReadBuffer!=ctx->Color.DrawBuffer;
  225.  
  226.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  227.       /* read */
  228.       if (setbuffer) {
  229.          (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  230.       }
  231.       gl_read_index_span( ctx, width, srcx, sy, indx );
  232.  
  233.       /* shift, offset */
  234.       if (ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset) {
  235.          if (ctx->Pixel.IndexShift<0) {
  236.             for (i=0;i<width;i++) {
  237.                indx[i] = (indx[i] >> -ctx->Pixel.IndexShift)
  238.                          + ctx->Pixel.IndexOffset;
  239.             }
  240.          }
  241.          else {
  242.             for (i=0;i<width;i++) {
  243.                indx[i] = (indx[i] << ctx->Pixel.IndexShift)
  244.                          + ctx->Pixel.IndexOffset;
  245.             }
  246.          }
  247.       }
  248.  
  249.       /* mapping */
  250.       if (ctx->Pixel.MapColorFlag) {
  251.          for (i=0;i<width;i++) {
  252.             if (indx[i] < ctx->Pixel.MapItoIsize) {
  253.                indx[i] = ctx->Pixel.MapItoI[ indx[i] ];
  254.             }
  255.          }
  256.       }
  257.  
  258.       /* write */
  259.       if (setbuffer) {
  260.          (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  261.       }
  262.       if (zoom) {
  263.          gl_write_zoomed_index_span( ctx, width, destx, dy, zspan, indx, desty );
  264.       }
  265.       else {
  266.          gl_write_index_span( ctx, width, destx, dy, zspan, indx, GL_BITMAP );
  267.       }
  268.    }
  269. }
  270.  
  271.  
  272.  
  273. /*
  274.  * TODO: Optimize!!!!
  275.  */
  276. static void copy_depth_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
  277.                                GLint width, GLint height,
  278.                                GLint destx, GLint desty )
  279. {
  280.    GLfloat depth[MAX_WIDTH];
  281.    GLdepth zspan[MAX_WIDTH];
  282.    GLuint indx[MAX_WIDTH];
  283.    GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  284.    GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  285.    GLint sy, dy, stepy;
  286.    GLint i, j;
  287.    GLboolean zoom;
  288.  
  289.    if (!ctx->Buffer->Depth) {
  290.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  291.       return;
  292.    }
  293.  
  294.    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  295.       zoom = GL_FALSE;
  296.    }
  297.    else {
  298.       zoom = GL_TRUE;
  299.    }
  300.  
  301.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  302.    if (srcy<desty) {
  303.       /* top-down  max-to-min */
  304.       sy = srcy + height - 1;
  305.       dy = desty + height - 1;
  306.       stepy = -1;
  307.    }
  308.    else {
  309.       /* bottom-up  min-to-max */
  310.       sy = srcy;
  311.       dy = desty;
  312.       stepy = 1;
  313.    }
  314.  
  315.    /* setup colors or indexes */
  316.    if (ctx->Visual->RGBAflag) {
  317.       GLubyte r, g, b, a;
  318.       r = ctx->Current.IntColor[0];
  319.       g = ctx->Current.IntColor[1];
  320.       b = ctx->Current.IntColor[2];
  321.       a = ctx->Current.IntColor[3];
  322.       MEMSET( red,   (int) r, width );
  323.       MEMSET( green, (int) g, width );
  324.       MEMSET( blue,  (int) b, width );
  325.       MEMSET( alpha, (int) a, width );
  326.    }
  327.    else {
  328.       for (i=0;i<width;i++) {
  329.          indx[i] = ctx->Current.Index;
  330.       }
  331.    }
  332.  
  333.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  334.       /* read */
  335.       (*ctx->Driver.ReadDepthSpanFloat)( ctx, width, srcx, sy, depth );
  336.       /* scale, bias, clamp */
  337.       for (i=0;i<width;i++) {
  338.          GLfloat d = depth[i] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
  339.          zspan[i] = (GLint) (CLAMP( d, 0.0, 1.0 ) * DEPTH_SCALE);
  340.       }
  341.       /* write */
  342.       if (ctx->Visual->RGBAflag) {
  343.          if (zoom) {
  344.             gl_write_zoomed_color_span( ctx, width, destx, dy, zspan,
  345.                                         red, green, blue, alpha, desty );
  346.          }
  347.          else {
  348.             gl_write_color_span( ctx, width, destx, dy, zspan,
  349.                                  red, green, blue, alpha, GL_BITMAP );
  350.          }
  351.       }
  352.       else {
  353.          if (zoom) {
  354.             gl_write_zoomed_index_span( ctx, width, destx, dy,
  355.                                         zspan, indx, desty);
  356.          }
  357.          else {
  358.             gl_write_index_span( ctx, width, destx, dy,
  359.                                  zspan, indx, GL_BITMAP );
  360.          }
  361.       }
  362.    }
  363. }
  364.  
  365.  
  366.  
  367. static void copy_stencil_pixels( GLcontext* ctx, GLint srcx, GLint srcy,
  368.                                  GLint width, GLint height,
  369.                                  GLint destx, GLint desty )
  370. {
  371.    GLubyte stencil[MAX_WIDTH];
  372.    GLint sy, dy, stepy;
  373.    GLint i, j;
  374.    GLboolean zoom;
  375.  
  376.    if (!ctx->Buffer->Stencil) {
  377.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  378.       return;
  379.    }
  380.  
  381.    if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
  382.       zoom = GL_FALSE;
  383.    }
  384.    else {
  385.       zoom = GL_TRUE;
  386.    }
  387.  
  388.    /* Determine if copy should be bottom-to-top or top-to-bottom */
  389.    if (srcy<desty) {
  390.       /* top-down  max-to-min */
  391.       sy = srcy + height - 1;
  392.       dy = desty + height - 1;
  393.       stepy = -1;
  394.    }
  395.    else {
  396.       /* bottom-up  min-to-max */
  397.       sy = srcy;
  398.       dy = desty;
  399.       stepy = 1;
  400.    }
  401.  
  402.    for (j=0; j<height; j++, sy+=stepy, dy+=stepy) {
  403.       /* read */
  404.       gl_read_stencil_span( ctx, width, srcx, sy, stencil );
  405.       /* shift, offset */
  406.       if (ctx->Pixel.IndexShift<0) {
  407.          for (i=0;i<width;i++) {
  408.             stencil[i] = (stencil[i] >> -ctx->Pixel.IndexShift)
  409.                          + ctx->Pixel.IndexOffset;
  410.          }
  411.       }
  412.       else {
  413.          for (i=0;i<width;i++) {
  414.             stencil[i] = (stencil[i] << ctx->Pixel.IndexShift)
  415.              + ctx->Pixel.IndexOffset;
  416.          }
  417.       }
  418.       /* mapping */
  419.       if (ctx->Pixel.MapStencilFlag) {
  420.          for (i=0;i<width;i++) {
  421.             if ((GLint) stencil[i] < ctx->Pixel.MapStoSsize) {
  422.                stencil[i] = ctx->Pixel.MapStoS[ stencil[i] ];
  423.             }
  424.          }
  425.       }
  426.       /* write */
  427.       if (zoom) {
  428.          gl_write_zoomed_stencil_span( ctx, width, destx, dy, stencil, desty );
  429.       }
  430.       else {
  431.          gl_write_stencil_span( ctx, width, destx, dy, stencil );
  432.       }
  433.    }
  434. }
  435.  
  436.  
  437.  
  438.  
  439. void gl_CopyPixels( GLcontext* ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height,
  440.             GLenum type )
  441. {
  442.    GLint destx, desty;
  443.  
  444.    if (INSIDE_BEGIN_END(ctx)) {
  445.       gl_error( ctx, GL_INVALID_OPERATION, "glCopyPixels" );
  446.       return;
  447.    }
  448.  
  449.    if (width<0 || height<0) {
  450.       gl_error( ctx, GL_INVALID_VALUE, "glCopyPixels" );
  451.       return;
  452.    }
  453.  
  454.    if (ctx->NewState) {
  455.       gl_update_state(ctx);
  456.    }
  457.  
  458.    if (ctx->RenderMode==GL_RENDER) {
  459.       /* Destination of copy: */
  460.       if (!ctx->Current.RasterPosValid) {
  461.      return;
  462.       }
  463.       destx = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
  464.       desty = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
  465.  
  466.       if (type==GL_COLOR && ctx->Visual->RGBAflag) {
  467.          copy_rgb_pixels( ctx, srcx, srcy, width, height, destx, desty );
  468.       }
  469.       else if (type==GL_COLOR && !ctx->Visual->RGBAflag) {
  470.          copy_ci_pixels( ctx, srcx, srcy, width, height, destx, desty );
  471.       }
  472.       else if (type==GL_DEPTH) {
  473.          copy_depth_pixels( ctx, srcx, srcy, width, height, destx, desty );
  474.       }
  475.       else if (type==GL_STENCIL) {
  476.          copy_stencil_pixels( ctx, srcx, srcy, width, height, destx, desty );
  477.       }
  478.       else {
  479.      gl_error( ctx, GL_INVALID_ENUM, "glCopyPixels" );
  480.       }
  481.    }
  482.    else if (ctx->RenderMode==GL_FEEDBACK) {
  483.       GLfloat color[4];
  484.       color[0] = ctx->Current.IntColor[0] * ctx->Visual->InvRedScale;
  485.       color[1] = ctx->Current.IntColor[1] * ctx->Visual->InvGreenScale;
  486.       color[2] = ctx->Current.IntColor[2] * ctx->Visual->InvBlueScale;
  487.       color[3] = ctx->Current.IntColor[3] * ctx->Visual->InvAlphaScale;
  488.       FEEDBACK_TOKEN( ctx, (GLfloat) GL_COPY_PIXEL_TOKEN );
  489.       gl_feedback_vertex( ctx, ctx->Current.RasterPos[0],
  490.               ctx->Current.RasterPos[1],
  491.               ctx->Current.RasterPos[2],
  492.               ctx->Current.RasterPos[3],
  493.               color, ctx->Current.Index,
  494.               ctx->Current.TexCoord );
  495.    }
  496.    else if (ctx->RenderMode==GL_SELECT) {
  497.       gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
  498.    }
  499.  
  500. }
  501.  
  502.  
  503.